#include "gps_usart.h"  // 包含自定义的头文件
#include "cJSON.h"  // 包含 cJSON 库

void gps_usart_init(uint32_t baudrate)
{
    uart_config_t uart_config;  // 串口配置句柄

    uart_config.baud_rate = baudrate;  // 波特率
    uart_config.data_bits = UART_DATA_8_BITS;  // 字长为8位数据格式
    uart_config.parity = UART_PARITY_DISABLE;  // 无奇偶校验位
    uart_config.stop_bits = UART_STOP_BITS_1;  // 一个停止位
    uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;  // 无硬件控制流
    uart_config.source_clk = UART_SCLK_APB;  // 配置时钟源
    uart_config.rx_flow_ctrl_thresh = 122;  // 硬件控制流阈值
    uart_param_config( GPS_USART_UX , &uart_config);  // 配置 UART 端口

    // 配置 UART 引脚
    uart_set_pin( GPS_USART_UX , GPS_USART_TX_GPIO_PIN, GPS_USART_RX_GPIO_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    // 安装串口驱动
    uart_driver_install(GPS_USART_UX, GPS_RX_BUF_SIZE, 0, 0, NULL, 0);
}


// 校验和验证函数
uint8_t calculate_checksum(const char *sentence) {
    uint8_t checksum = 0;
    const char *start = strchr(sentence, '$');
    if (start == NULL) return 0;
    const char *end = strchr(start, '*');
    if (end == NULL) return 0;
    for (const char *p = start + 1; p < end; ++p) {
        checksum ^= *p;
    }
    return checksum;
}

bool validate_checksum(const char *sentence) {
    const char *checksum_str = strchr(sentence, '*');
    if (checksum_str == NULL) return false;
    checksum_str += 1; // 跳过 '*' 符号
    uint8_t checksum = strtol(checksum_str, NULL, 16);
    return checksum == calculate_checksum(sentence);
}


// 定义 NMEA 句子解析函数
void parse_GNGGA(const char* sentence, cJSON* json) {
    char data[100];

    // 解析时间
    sscanf(sentence, "$GNGGA,%[^,],", data);
    cJSON_AddStringToObject(json, "Time", data);

    // 解析纬度
    sscanf(sentence, "%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Latitude", data);

    // 解析纬度方向
    sscanf(sentence, "%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "LatitudeDirection", data);

    // 解析经度
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Longitude", data);

    // 解析经度方向
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "LongitudeDirection", data);

    // 解析卫星数量
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Satellites", data);

    // 解析 HDOP
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "HDOP", data);

    // 解析海拔高度
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Altitude", data);
}

void parse_GNRMC(const char* sentence, cJSON* json) {
    char data[100];

    // 解析时间
    sscanf(sentence, "$GNRMC,%[^,],", data);
    cJSON_AddStringToObject(json, "Time", data);

    // 解析状态
    sscanf(sentence, "%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Status", data);

    // 解析纬度
    sscanf(sentence, "%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Latitude", data);

    // 解析纬度方向
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "LatitudeDirection", data);

    // 解析经度
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Longitude", data);

    // 解析经度方向
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "LongitudeDirection", data);

    // 解析速度
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Speed", data);

    // 解析航向
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Course", data);

    // 解析日期
    sscanf(sentence, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,],", data);
    cJSON_AddStringToObject(json, "Date", data);
}

void parse_GPS_sentences(const char* sentences, cJSON* json) {
    char* token;
    char* sentences_copy = strdup(sentences);

    token = strtok(sentences_copy, "\n");
    while (token) {
        if (strncmp(token, "$GNGGA", 6) == 0) {
            cJSON_AddItemToObject(json, "GNGGA", cJSON_CreateObject());
            parse_GNGGA(token, cJSON_GetObjectItem(json, "GNGGA"));
        } else if (strncmp(token, "$GNRMC", 6) == 0) {
            cJSON_AddItemToObject(json, "GNRMC", cJSON_CreateObject());
            parse_GNRMC(token, cJSON_GetObjectItem(json, "GNRMC"));
        }
        token = strtok(NULL, "\n");
    }

    free(sentences_copy);
}